- /* sdfdsdiv.cpp by K.Tsuru */
- // function ID = 325 DRADIX only
- /*********************************************************************
- SDouble class
- It divides 'm' by a small integer 'n'.
- m/n 0 < n < ULONG_MAX/radix
- Pay attention to the case in which the result is a recurring decimal.
- *********************************************************************/
- #ifndef SN_H
- #include "sn.h"
- #endif
- static const char* func = "DsDiv"; // add "const" since version 2.192
- /*****************************************************************
- sub-function
- It checks that "1/x" is a recurring decimal or not in radix DRADIX.
- ******************************************************************/
- static int IsCyclic(ulong x){
- if(x == 0) return 0;
- while((x % 2uL) == 0) x /= 2uL;
- if(x == 1uL) return 0; // x = 2^p
- while((x % 5uL) == 0) x /= 5uL;
- return x != 1uL;
- }
- SDouble DsDiv(const SDouble& m, ulong n){
- ulong rdx = (ulong)m.Radix();
- const uint minFig = 7u; //It reserves 7 figures(size is 8) at least.
- if(rdx != DRADIX) m.SetError(m.RADIX_ERR, "Use XsDiv", 325);
- if( n > m.SlOpMaxValue() ) m.SetError(m.OUT_OF_RANGE, func, 325);
- if( (n == 1uL) || (m.Sign(325) == 0) ) return m;
- if(n == 0) m.SetError(m.DIVIDED_BY_ZERO, func, 325);
-
- uint cur_max_sz = m.CurrentMaxSize(), rsz;
- SDouble result;
- ulong w, r;
- int i, j, top, end, rf, shift = 0;
- //"result" is a long decimal?
- int rIsLong = (m.Last() >= cur_max_sz) ? 1 : IsCyclic(n);
- //The series function calls this one many times in the fixed point mode.
- //It separately treats the floating point and fixed point modes to gain speed.
- fType* rv;
- if(!m.IsPointFixed()){ //floating point mode
- const fType* mv;
- result.rdxExp = m.rdxExp;
- mv = m.ReadFigures();
- top = 1;
- end = (int)min(m.Last(), cur_max_sz-1u);//The Pi() has figures more than "cur_max_sz".
- rsz = rIsLong ? cur_max_sz : max((uint)end+1u, minFig);
- result.valloc(rsz, 0);
- rv = result.figure.Elements();
- w = mv[1]/n; //It checks whether the first figure of quotient is zero ot not.
- if(w == 0){ //first figure is zero
- rf = 1; shift = 1; r = mv[1];
- w = r*rdx+mv[2];//first two figures
- if( w < n){ //second figure is also zero
- shift++; r = w; //It takes first two figures as remainder 'r'.
- }
- result.rdxExp -= shift; //to set upper position by 'shift'
- } else {
- rv[1] = (fType)w; //set the first decimal place
- r = mv[1]%n; rf = 2;
- }
- end -= shift; // i+shift <= end+shift <= m.Last(), end < cur_max_sz
- if(end <= 0){ //It may occure when it devides one figure by 'n'.
- end = 0; i = 1; top = 0;
- } else {
- #ifndef NDEBUG
- m.figure(end+shift); result.figure(end);
- #endif
- for(i = rf; i <= end; i++){
- w = rdx*r + mv[i+shift];
- rv[i] = fType(w/n);
- r = w - rv[i]*n; // r = w%n;
- }
- }
- } else { //fixed point mode
- SDouble mc;
- const fType* mf;
- int de = m.rdxExp - m.fixedExp;
- if(de){ //The exponent value is different from the fixed one.
- mc = m; //copy of m
- mc.Reform(325); //By moving figures it makes the same exponent.
- de = mc.rdxExp - m.fixedExp;
- if( (de > 0) && ((ulong)mc.figure(1) < n) ){
- //In spite of "Reform()" de > 0. mc=0.xxxx yyyy ....
- //The first figure of quotient is zero. 0.xxxx yyyy --> xxxx.yyyy
- mc.ShiftArray(-1); mc.rdxExp--;
- }
- //It maybe becomes mc=0 by "Reform()" or substitution.
- if(mc.Sign() == 0){ result.SetZero(); return result; }
- result.rdxExp = mc.rdxExp;
- top = (int)mc.First();
- end = (int)min(mc.Last(), cur_max_sz-1u);
- mf = mc.ReadFigures();
- #ifndef NDEBUG
- mc.figure(end);
- #endif
- } else {
- result.rdxExp = m.rdxExp;
- top = (int)m.First();
- end = (int)min(m.Last(), cur_max_sz-1u);
- mf = m.ReadFigures();
- }
- rsz = rIsLong ? cur_max_sz : max((uint)end+1u, minFig);
- result.valloc(rsz, -1);
- result.figure.clear(0, (uint)top);
- result.figure.clear((uint)end+1u);
- rv = result.figure.Elements();
- #ifndef NDEBUG
- result.figure(end);
- #endif
- r = 0;
- for( i = top; i <= end; i++){
- w = rdx*r + mf[i];
- rv[i] = fType(w/n);
- r = w - rv[i]*n; // r = w%n;
- }
- }
- #ifndef NDEBUG
- assert(end >= top);
- #endif
- /******** processing common to floating and fixed point modes **********/
- //processing for non-zero remainder
- if(r && !rIsLong){ //Meybe the result is a finite decimal fraction.
- int z = (int)min(result.figure.size(), cur_max_sz);
- z = min(z, i+4);
- for(; r && (i < z); i++){
- w = rdx*r;
- rv[i] = fType(w/n);
- r = w - rv[i]*n; // r = w%n;
- }
- end = i-1;
- }
-
- if(r && (end < (int)cur_max_sz)){
- result.valloc(cur_max_sz, 1);
- rv = result.figure.Elements();
- #ifndef NDEBUG
- result.figure(cur_max_sz-1);
- #endif
- for( ; i < (int)cur_max_sz; i++){
- //Here it is almost aliquant, then "r==0" is not checked.
- w = rdx*r;
- rv[i] = fType(w/n);
- r = w - rv[i]*n; // r = w%n;
- }
- end = (int)cur_max_sz-1;
- //In the case 2*r>=n it can raise up the precision by the rounding
- //but the processing becomes complicated.
- }
- #ifndef NDEBUG
- result.figure(end);
- #endif
- //check the figure positions
- j = end;
- rv = result.figure.Elements();
- while(!rv[j] && (j > top) ) j--;
-
- if( (j == top) && (result.figure(j) == 0) ){ //It becomes zero.
- result.rdxExp = 0;
- result.SetSign(0); //only in the fixed point mode, SetZero() not necessary
- return result;
- }
- result.aHead = (uint)j;
-
- i = top;
- while(!rv[i]) i++;
- result.aTail = i;
-
- result.SetSign( m.Sign(325) );
- result.Reform(325);
- return result;
- }
sdfdsdiv.cpp : last modifiled at 2017/03/13 14:31:58(5,571 bytes)
created at 2017/10/07 10:22:50
The creation time of this html file is 2017/10/07 11:29:39 (Sat Oct 07 11:29:39 2017).